<?php
/***************************************************************************
 * 
 * Copyright (c) 2010 , Inc. All Rights Reserved
 * 
 **************************************************************************/
 
 
 
/**
 * @file DataGenerator.php
 * @author mall(com@)
 * @date 2010/11/29 14:06:23
 * @brief 
 *  
 **/

final class DataGenerator
{
    private $path;
    private $mod;
    private $file;
    private $rootdsl;
    private $encoding;

    function __construct($dslpath,$mod,$encoding)
    {
        $this->path = rtrim($dslpath,'/');
        $this->mod = $mod;
        $this->encoding = $encoding;
    }

    function genData($func)
    {
        $dslfile = $this->path.'/'.$this->mod.'/'.$func.'.json';
        if (is_readable($dslfile)) {
            $this->file = $dslfile;
            $data = file_get_contents($dslfile);
            $dsl = json_decode($data,true);
            if ($this->encoding != "UTF8") {
                 mb_convert_variables($this->encoding,"UTF8",$dsl);
            }
            if ($dsl) {
                $this->rootdsl = $dsl;
                $ret = $this->_genData($dsl);
                return array('data'=>$ret);
            } else {
                throw new Exception('autodsl.invalidjson');
            }
        }
        return false;
    }

    private function _genData($datadsl)
    {
        if (empty($datadsl['return'])) {
            throw new Exception("autodsl.invaliddsl ".print_r($datadsl,true));
        }
        if (isset($datadsl['data'])) {
            return $datadsl['data'];
        }
        $ret = explode(":",$datadsl['return']);
        if ($ret[0]=='list') {
            //列表
            return $this->_genList($datadsl);
        } elseif ($ret[0]=='a') {
            //简单列表
            return $this->_genArray($datadsl);
        } elseif ($ret[0]=='obj') {
            //单个对象
            return $this->_genObject($datadsl);
        } else {
            return $this->_genValue($datadsl['return']);
        }

    }

    private function _genList($dsl)
    {
        $return = $dsl['return'];
        $arr = explode(":",$return);
        if (!isset($arr[1])) {
            $arr[1] = 100;
            $arr[2] = 20;
        } else {
            $tmp = explode("-",$arr[1]);
            $arr[1] = $tmp[0];
            $arr[2] = $tmp[1];
        }
        $total = $arr[1];
        $size = $arr[2];
        $list = array();
        for($i=0;$i<$size;$i++) {
            $list[] = $this->_genObject($dsl);
        }
        return array(
            'tn'=>$total,
            'size'=>$size,
            'data'=>$list
        );
    }

    private function _genArray($dsl)
    {
        //生成一个平面列表
        $return = $dsl['return'];
        $arr = explode(":",$return);
        if (!isset($arr[1])) {
            $arr[1] = 20;
        }
        $size = $arr[1];
        $list = array();
        for($i=0;$i<$size;$i++) {
            $list[] = $this->_genObject($dsl);
        }
        return $list;
    }

    private function _genObject($dsl)
    {
        if (empty($dsl['field'])) {
            throw new Exception("autodsl.invaliddsl ".print_r($dsl));
        }
        $fields = $dsl['field'];
        $object = array();
        foreach($fields as $field) {
            $col = explode(":",$field);
            if (!isset($col[1])) {
                $col[] = 's';
            }
            if ($col[1] == 'obj') {
                $fieldKey = $col[2];
                $objdsl = $this->rootdsl[$fieldKey];
                $value = $this->_genObject($objdsl);
            } elseif ($col[1] == 'a') {
                $fieldKey = $col[2];
                $adsl = $this->rootdsl[$fieldKey];
                $value = $this->_genArray($adsl);
            } elseif ($col[1] == 'list') {
                $fieldKey = $col[2];
                $listdsl = $this->rootdsl[$fieldKey];
                $value = $this->_genList($listdsl);
            } else { 
                $type = $col[1];
                if (isset($col[2])) {
                    $type .= ":".$col[2];
                }
                $value = $this->_genValue($type);
            }
            $object[$col[0]] = $value;
        }
        return $object;
    }

    //生成元始类型值
    private function _genValue($type)
    {
        $pos = strpos($type,':');
        if ($pos) {
            $ret = array(substr($type,0,$pos),substr($type,$pos+1));
        } else {
            $ret = array($type);
        }
        $expr = '';
        if (strncmp($type,'{',1) === 0) {
            $expr = trim($type,'{}');
        } else if (isset($ret[1])) {
            //如果设置了类型扩展属性
            //{}之中的内容会被认为是php代码，按照代码的方式执行，返回结果当作值.
            if (strncmp($ret[1],'{',1) === 0) {
                //把前后{}去掉
                $expr = trim($ret[1],'{}');
            }
        }
        if ($expr) {
            $code = '$_tmpv_='.$expr.';';
            eval($code);
            if (!isset($_tmpv_)) {
                return null;
            } else {
                return $_tmpv_;
            }
        }
        if ($ret[0]=='b') {
            //布尔
            $set = empty($ret[1])?'rand':$ret[1];
            return $this->_genBool($set);
        } elseif ($ret[0]=='i') {
            //整数
            $range = empty($ret[1])?array(0,1000):explode("-",$ret[1]);
            return $this->_genInt($range[0],$range[1]);
        } elseif ($ret[0]=='n') {
            //名称
            $range = empty($ret[1])?array(5,20):explode("-",$ret[1]);
            return $this->_genName($range[0],$range[1]);
        } elseif ($ret[0]=='t') {
            //大文本
            $range = empty($ret[1])?array(100,1000):explode("-",$ret[1]);
            return $this->_genText($range[0],$range[1]);
        } elseif ($ret[0]=='f') {
            //浮点数
            $range = empty($ret[1])?array(0,1000,2):explode("-",$ret[1]);
            return $this->_genFloat($range[0],$range[1],$range[2]);
        } elseif ($ret[0]=='null' || $ret[0] == 'void') {
            return null;
        } else { // ($ret[0]=='s') 
            //字符串
            $range = empty($ret[1])?array(3,20):explode("-",$ret[1]);
            return $this->_genString($range[0],$range[1]);
        }
    }

    private function _genBool($ret='rand')
    {
        if ($ret === 'rand') {
            $num = mt_rand(1,10);
            return ($num%2) == 1;
        } else {
            return !!$ret;
        }
    }

    private function _genString($min=3,$max=20)
    {
        $tpl = 'Aa1';
        $num = mt_rand($min,$max);
        return str_repeat($tpl,$num/3);
    }

    private function _genName($min=5,$max=20)
    {
        $tpl = 'A我是标题';
        $num = mt_rand($min,$max);
        return str_repeat($tpl,$num/5);
    }

    private function _genInt($min=0,$max=1000)
    {
        return mt_rand($min,$max);
    }

    private function _genText($min=100,$max=1000)
    {
        $tpl = '汉字+zi母';
        $num = mt_rand($min,$max);
        return str_repeat($tpl,$num/6);
    }

    private function _genFloat($min=0,$max=1000,$subfix=2)
    {
        $subfixmax = pow(10,$subfix)-1;
        $subfixmin = 0;
        $num = mt_rand($min,$max);
        $snum = mt_rand($subfixmin,$subfixmax);
        return floatval("$num.$snum");
    }
}





/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */